#pragma once

#include "../common/net.hpp"
#include "../common/message.hpp"

namespace RPC_project
{
    namespace server
    {
        // 枚举出rpcrequest中参数的类型(bool int float string array object)
        enum class VType
        {
            BOOL = 0,
            INTEGRAL,
            NUMERIC,
            STRING,
            ARRAY,
            OBJECT,

        };

        //
        class ServiceDescribe
        {
        public:
            using ptr = std::shared_ptr<ServiceDescribe>;
            // 业务回调函数 利用request中的参数进行处理, 构成response的返回参数
            using ServiceCallback = std::function<void(const Json::Value &, Json::Value &)>;

            // request中的参数信息描述<参数名字 ,参数类型>
            using ParamsDescribe = std::pair<std::string, VType>;
            ServiceDescribe(std::string &&name, std::vector<ParamsDescribe> &&desc, ServiceCallback &&handler, VType vtype)
                : _method_name(std::move(name)), _callback(std::move(handler)), _params_desc(std::move(desc)), _return_type(vtype)
            {
            }

            bool paramCheck(const Json::Value &params)
            {
                // 对params进行参数校验 1.检查所描述的参数字段是否存在 ,参数字段的类型是否正确
                for (auto &desc : _params_desc)
                {
                    if (params.isMember(desc.first) == false)
                    {
                        ELOG("参数字段完整性校验失败！%s 字段缺失！", desc.first.c_str());
                    }
                    if (check(desc.second, params[desc.first]) == false)
                    {
                        ELOG("%s 参数类型校验失败！", desc.first.c_str());
                        return false;
                    }
                }
                return true;
            }
            //接口调用
            bool call(const Json::Value &params, Json::Value &result)
            {
                _callback(params, result);
                if (rtypeCheck(result) == false)
                {
                    ELOG("回调处理函数中的响应信息校验失败！");
                    return false;
                }
                return true;
            }
            std::string methodName()
            {
                return _method_name;
            }


        private:
            bool rtypeCheck(const Json::Value &val)
            {
                return check(_return_type, val);
            }
            bool check(VType vtype, const Json::Value &val)
            {
                switch (vtype)
                {
                case VType::BOOL:
                    return val.isBool();
                case VType::INTEGRAL:
                    return val.isIntegral();
                case VType::NUMERIC:
                    return val.isNumeric();
                case VType::STRING:
                    return val.isString();
                case VType::ARRAY:
                    return val.isArray();
                case VType::OBJECT:
                    return val.isObject();
                }
                return false;
            }

        private:
            std::string _method_name;                 // ⽅法名称
            ServiceCallback _callback;                // 实际的业务回调函数
            std::vector<ParamsDescribe> _params_desc; // 参数字段格式描述(名称 : 类型)
            VType _return_type;                       // 结果作为返回值类型的描述
        };

        class SDescribeFactory
        {
        public:
            using ptr = std::shared_ptr<SDescribeFactory>;

            void setMethodName(const std::string &name)
            {
                _method_name = name;
            }
            void setReturnType(VType type)
            {
                _return_type = type;
            }

            void setParamsDesc(const std::string &pname, VType type)
            {
                _params_desc.push_back(ServiceDescribe::ParamsDescribe(pname, type));
            }
            void setCallback(const ServiceDescribe::ServiceCallback &cb)
            {
                _callback = cb;
            }

            // 建造者模式
            ServiceDescribe::ptr build()
            {
                return std::make_shared<ServiceDescribe>(std::move(_method_name), std::move(_params_desc), std::move(_callback),_return_type);
            }

        private:
            std::string _method_name;
            ServiceDescribe::ServiceCallback _callback;                // 实际的业务回调函数
            std::vector<ServiceDescribe::ParamsDescribe> _params_desc; // 参数字段格式描述(名称 : 类型)
            VType _return_type;                                        // 结果作为返回值类型的描述
        };

        // 服务器会有多种服务 ,用hash管理服务
        class ServiceManager
        {
        public:
            using ptr = std::shared_ptr<ServiceManager>;
            //增
            void insert(const ServiceDescribe::ptr& desc )
            {
                std::unique_lock<std::mutex> lock(_mutex);
                _services.insert(std::make_pair(desc->methodName() , desc));
            }
            //查
            ServiceDescribe::ptr  select(const std::string & methodname)
            {
                std::unique_lock<std::mutex> lock(_mutex);

                auto it=_services.find(methodname);
                if(it == _services.end())
                {
                    return ServiceDescribe::ptr();
                }
                return it->second;
            }
            //删
            void remove(const std::string & methodnam)
            {
                std::unique_lock<std::mutex> lock(_mutex);
                _services.erase(methodnam);

            }
        private:
            std::mutex _mutex;
            std::unordered_map<std::string ,ServiceDescribe::ptr> _services;
        };


        //rpc的request的路由处理
        class RpcRouter
        {
        public:
            using ptr = std::shared_ptr<RpcRouter>;
            RpcRouter():_service_manager(std::make_shared<ServiceManager>())
            {
            }
            // 提供给dispatcher,注册进去处理Rpc请求
            void onRpcRequest(const BaseConnection::ptr &conn, RpcRequest::ptr &request)
            {
                // 1.检查客户端请求的方法描述 --->判断当前服务器能否提供方法实现
                auto service = _service_manager->select(request->Method());
                if(service == nullptr)
                {
                    ELOG("%s,当前服务在RpcRouter中未找到" ,request->Method().c_str());
                    return response(conn ,request ,Json::Value() ,RCode::RCODE_NOT_FOUND_SERVICE);
                }
                // 2.进行参数校验 ,确定能否提供服务
                if(service->paramCheck(request->Params()) == false)
                {
                    ELOG("%s,该请求的参数校验失败" ,request->Method().c_str());
                    return response(conn ,request ,Json::Value() ,RCode::RCODE_INVALID_PARAMS);
                }
                // 3.调用业务回调接口进行业务处理
                Json::Value result;
                bool ret = service->call(request->Params() ,result);
                if(ret == false)
                {
                    ELOG("%s,服务业务回调失败" ,request->Method().c_str());
                    return response(conn ,request ,Json::Value() ,RCode::RCODE_INTERNAL_ERROR);
                }
                // 4.处理完毕得到结果 ,形成响应(response) ,发送回客户端
                return response(conn ,request ,result ,RCode::RCODE_OK);
            }

            // 服务注册接口
            void registerMethod(const ServiceDescribe::ptr &service)
            {
                _service_manager->insert(service);
            }
        private:
            //构造返回的response
            void response(const BaseConnection::ptr &conn, RpcRequest::ptr &req ,Json::Value resp , RCode code)
            {
                auto msg = MessageFactory::Create(MType::RSP_RPC); 
                RPC_project::RpcResponse::ptr rpc_ptr = std::dynamic_pointer_cast<RPC_project::RpcResponse>(msg);

                rpc_ptr->Setid(req->Rid());
                rpc_ptr->SetMyType(MType::RSP_RPC);
                rpc_ptr->SetRcode(code);
                rpc_ptr->SetResult(resp);
                conn->Send(rpc_ptr);
            }
        private:
            ServiceManager::ptr _service_manager;
        };
    }
}
